package com.xq.shop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xq.shop.dao.domain.entity.*;
import com.xq.shop.dao.mapper.NetGoodsMapper;
import com.xq.shop.dto.EditGoodsDto;
import com.xq.shop.dto.IntegerDto;
import com.xq.shop.dto.QueryGoodsDto;
import com.xq.shop.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xq.shop.vo.NetGoodsDetailVo;
import com.xq.shop.vo.NetGoodsVo;
import enums.DataStatus;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import utils.BasePage;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author gaoxiaojin
 * @since 2024-07-24
 */
@Service
public class NetGoodsServiceImpl extends ServiceImpl<NetGoodsMapper, NetGoods> implements INetGoodsService {

    private final IGoodsDetailsImgService goodsDetailsImgService;
    private final IGoodsDetailsParameterService goodsDetailsParameterService;
    private final IGoodsDetailsPriceService goodsDetailsPriceService;
    private final IGoodsDetailsSpecService goodsDetailsSpecService;

    @Autowired
    public NetGoodsServiceImpl(IGoodsDetailsImgService goodsDetailsImgService, IGoodsDetailsParameterService goodsDetailsParameterService, IGoodsDetailsPriceService goodsDetailsPriceService, IGoodsDetailsSpecService goodsDetailsSpecService) {
        this.goodsDetailsImgService = goodsDetailsImgService;
        this.goodsDetailsParameterService = goodsDetailsParameterService;
        this.goodsDetailsPriceService = goodsDetailsPriceService;
        this.goodsDetailsSpecService = goodsDetailsSpecService;
    }

    @Override
    public BasePage<NetGoodsVo> pageQuery(QueryGoodsDto dto) {

        String inClause = null;
        if (!dto.getCategory().isEmpty()) {
            inClause = dto.getCategory().stream()
                    .map(s -> "'" + s + "'")
                    .collect(Collectors.joining(", "));
        }
        IPage<NetGoodsVo> page = baseMapper.page(new Page<>(dto.getPage(), dto.getLimit()), dto, inClause);
        List<NetGoodsVo> goodsList = page.getRecords();
        if (goodsList.isEmpty()) {
            return new BasePage<NetGoodsVo>().initPage(dto.getPage(), dto.getLimit(), page.getTotal(), page.getPages(), new ArrayList<>());
        }
        for (NetGoodsVo goods : goodsList) {
            if (goods.getImgUrl() != null) {
                goods.setImgUrl("https://www.xq1688.com/ywxq-api/file/proxy/image?url=" + goods.getImgUrl());
            }
        }
        return new BasePage<NetGoodsVo>().initPage(dto.getPage(), dto.getLimit(), page.getTotal(), page.getPages(), goodsList);

    }

    @Override
    public NetGoodsDetailVo detail(IntegerDto dto) {
        NetGoods netGoods = getById(dto.getValue());
        if (Objects.isNull(netGoods)) {
            return new NetGoodsDetailVo();
        }
        NetGoodsDetailVo vo = new NetGoodsDetailVo();
        Map<String, Object> map = new HashMap<>();
        map.put("goods_id", netGoods.getGoodsId());
        List<GoodsDetailsImg> goodsDetailsImgList = (List<GoodsDetailsImg>) goodsDetailsImgService.listByMap(map);
        List<GoodsDetailsParameter> goodsDetailsParameterList = (List<GoodsDetailsParameter>) goodsDetailsParameterService.listByMap(map);
        List<GoodsDetailsSpec> goodsDetailsSpecList = (List<GoodsDetailsSpec>) goodsDetailsSpecService.listByMap(map);
        List<GoodsDetailsPrice> goodsDetailsPriceList = (List<GoodsDetailsPrice>) goodsDetailsPriceService.listByMap(map);
        vo.setRichText(netGoods.getRichText());
        vo.setGoodsDetailsImgList(goodsDetailsImgList);
        vo.setGoodsDetailsParameterList(goodsDetailsParameterList);
        vo.setGoodsDetailsSpecList(goodsDetailsSpecList);
        vo.setGoodsDetailsPriceList(goodsDetailsPriceList);
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(EditGoodsDto dto, Integer userId) {
        NetGoods goods = new NetGoods();
        if (dto.getId().equals(0)) {
            BeanUtils.copyProperties(dto, goods);
            goods.setCreateUser(userId);
            goods.setGoodsId(initGoodsId());
            save(goods);
        } else {
            goods = getById(dto.getId());
            BeanUtils.copyProperties(dto, goods);
            goods.setUpdateUser(userId);
            updateById(goods);
            Map<String, Object> map = new HashMap<>();
            map.put("goods_id", dto.getGoodsId());
            goodsDetailsImgService.removeByMap(map);
            goodsDetailsParameterService.removeByMap(map);
            goodsDetailsSpecService.removeByMap(map);
            goodsDetailsPriceService.removeByMap(map);
        }
        String goodsId = goods.getGoodsId();
        if (!dto.getGoodsDetailsImgList().isEmpty()) {
            List<GoodsDetailsImg> goodsDetailsImgList = new ArrayList<>();
            dto.getGoodsDetailsImgList().forEach(img -> {
                GoodsDetailsImg goodsDetailsImg = new GoodsDetailsImg();
                goodsDetailsImg.setGoodsId(goodsId);
                goodsDetailsImg.setImgUrl(img);
                goodsDetailsImgList.add(goodsDetailsImg);
            });
            goodsDetailsImgService.saveBatch(goodsDetailsImgList);
        }
        if (!dto.getGoodsDetailsParameterList().isEmpty()) {
            List<GoodsDetailsParameter> goodsDetailsParameterList = new ArrayList<>();
            dto.getGoodsDetailsParameterList().forEach(parameter -> {
                GoodsDetailsParameter goodsDetailsParameter = new GoodsDetailsParameter();
                BeanUtils.copyProperties(parameter, goodsDetailsParameter);
                goodsDetailsParameter.setGoodsId(goodsId);
                goodsDetailsParameterList.add(goodsDetailsParameter);
            });
            goodsDetailsParameterService.saveBatch(goodsDetailsParameterList);
        }
        if (!dto.getGoodsDetailsSpecList().isEmpty()) {
            Map<String, Integer> idMap = new LinkedHashMap<>(8);
            dto.getGoodsDetailsSpecList().forEach(s -> {
                GoodsDetailsSpec goodsDetailsSpec = new GoodsDetailsSpec();
                BeanUtils.copyProperties(s, goodsDetailsSpec);
                goodsDetailsSpec.setGoodsId(goodsId);
                goodsDetailsSpecService.save(goodsDetailsSpec);
                idMap.put(s.getFakeId(), goodsDetailsSpec.getId());
            });
            List<GoodsDetailsPrice> goodsDetailsPriceList = new ArrayList<>();
            dto.getGoodsDetailsPriceList().forEach(price -> {
                String[] fakeIds = price.getSelectSpecs().split(",");
                StringBuilder newIds = new StringBuilder();
                for (String fakeId : fakeIds) {
                    Integer newId = idMap.get(fakeId.trim());
                    if (newIds.length() > 0) {
                        newIds.append(",");
                    }
                    newIds.append(newId);
                }
                GoodsDetailsPrice goodsDetailsPrice = new GoodsDetailsPrice();
                BeanUtils.copyProperties(price, goodsDetailsPrice);
                goodsDetailsPrice.setGoodsId(goodsId);
                goodsDetailsPrice.setSelectSpecs(newIds.toString());
                goodsDetailsPriceList.add(goodsDetailsPrice);
            });
            goodsDetailsPriceService.saveBatch(goodsDetailsPriceList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeGoods(IntegerDto dto, Integer id) {
        NetGoods goods = getById(dto.getValue());
        goods.setStatus(DataStatus.INVALID.getCode());
        goods.setUpdateUser(id);
        updateById(goods);
        Map<String, Object> map = new HashMap<>();
        map.put("goods_id", goods.getGoodsId());
        goodsDetailsImgService.removeByMap(map);
        goodsDetailsParameterService.removeByMap(map);
        goodsDetailsSpecService.removeByMap(map);
        goodsDetailsPriceService.removeByMap(map);
    }

    private String initGoodsId() {
        String uuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8);
        LambdaQueryWrapper<NetGoods> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(NetGoods::getGoodsId, "ZY" + uuid);
        wrapper.eq(NetGoods::getBrandType, 0);
        NetGoods goods = getOne(wrapper);
        if (Objects.nonNull(goods)) {
            return initGoodsId();
        }
        return uuid;
    }

}
